System and method of conclusively verifying the correctness of an information system without needing to test every combination of behaviour at run-time

ABSTRACT

An architecture for the initial development and later adaptation of information systems comprising a database, one or more clients and any number of supporting libraries whose system data, application data and rule data are stored in the database alongside the content data so that the correctness of the system can be conclusively verified without having to test every combination of behaviour at run-time. 
     A framework in the database stores system, application and rule data and frameworks in the clients load the system, application and rule data to generate objects and, in doing so, define an domain-specific system. The integrity of system and application data is maintained by the database though predefined triggers and the integrity of content data is maintained by the database through triggers loading rule data and executing the rule definitions calling functions in dynamically linked libraries. The integrity of system and application data is maintained by each client though predefined rules in the meta system and the integrity of content data is maintained by the clients through an interpreter using rule data and executing the rule definitions calling functions in dynamically linked libraries. 
     Preferably the system structures, application structures, system data, application data, rule data and content data are stored in the same relational database but may instead be stored in different relational databases, in non-relational databases, in any persistent store or an in-memory structure; all application-specific properties and events are stored in the database but some properties and events can be stored external to the database; the integrity checking occurs both at the user-interface or client and then again at the database but such checks could occur any number of times at the point of selecting the options in the user-interface, in a middleware application through which data is passed between the user-interface or client and the database, or on committing the changes in the database.

BACKGROUND

Information systems are well known. Examples include accounting, stock control and contact management systems. At a simple level, each of these systems consists of a database and one or more clients. At an intermediate level of detail, they consist of data types, tables, forms and scripts. At a more detailed level, and information system consists of data types, tables, fields, datasets, forms, widgets and scripts.

While a stock control system will have a different set of data types, tables, fields, datasets, forms and scripts to a contact management system, both information systems are made up of substantially the same components. It is in the number and behaviour of these components that these information systems differ.

The design of information systems ranges from those which are fixed and cannot be customized by the end-user, to those which allow limited customization by providing extra fields in selected tables in the database for the end-user to store custom data and by allowing a scripting language so that custom processes can be enforced, through to development frameworks that allow the end-user to develop whatever data structures, forms and rules their organization requires. Run-the-Office falls into this last category by allowing end-users to develop whatever data structures, forms and rules their organization requires.

An information system development framework is further defined as program which does not have any domain-specific data or logic built in. This might include tables, fields and scripts which are specific to particular domain like accounting, stock control or contact management even though these may be customized by the end-user.

Information systems consist of a database and one or more clients. The clients connect to the database and execute SQL statements against the database to read, update, insert and delete data from the database and execute scripts to enforce rules. It is essential that these SQL statements and rules be valid in that any tables and fields referenced in the SQL statement or rule must exist in the database. In addition, the data types of the data sent from the client to the database must match or be compatible with the type of data expected by the database and that the data types of the data returned from the database to the client must match or be compatible with the type of data expected by the client.

Given that SQL statements can be stored as strings as properties of forms, embedded into scripts or dynamically generated by filter interfaces it is difficult, although not impossible, for clients to ensure that any SQL stored in the client is valid at the time of saving any changes to the client. However, because the database and any clients are separate applications, the structure of the database can be changed outside the control of any client designed to maintain the validity of the SQL statements it contains.

When this happens and the SQL sent from the client to the database does not match tables, fields or data types existing in the database or the data returned by the database to the client does not match that which the client expects then the behaviour of the client can be unpredictable.

The only way to conclusively verify the correctness of an information system consisting of a database and one or more clients is to test every combination of behaviour at run-time. This means testing every SQL statement sent from the client to the database to ensure it refers to existing tables and fields and sends compatible data types and every instance of data returned by the database to ensure it returns compatible data types.

Given that scripts are embedded into the clients it is difficult, although not impossible, for clients to ensure that any references to tables, fields and data types stored in the client are valid at the time of saving any changes to the client. However, because the database and any clients are separate applications, the structure of the database can be changed outside the control of any client designed to maintain the validity of the scripts it contains.

When this happens and the tables, fields and data types referenced in the scripts do not match tables, fields or data types existing in the database or the data returned by the database to the client does not match that which the client expects then the behaviour of the client can be unpredictable.

The only way to conclusively verify the correctness of an information system consisting of a database and one or more clients is to test every combination of behaviour at run-time. This means testing every script in the client to ensure it refers to existing tables and fields and sends compatible data types and every instance of data returned by the database to ensure it returns compatible data types.

In information systems which are fixed and cannot be customized by the end-user or which can be customized in very limited and predetermined ways this verification is the responsibility of the vendor or developer. In development frameworks that allow the end-user to develop whatever data structures, forms and rules their organization requires this verification is the responsibility of the end-user. In this latter type, where the reality of development is of continuous adaptation, the need to keep the database and the clients synchronized by testing every combination of behaviour at run-time makes the process particularly error-prone and time-consuming.

However, the problem still persists in all information systems where the database and the clients are separate applications and where the database can be changed independently of the client, for the database and the clients to expect different tables, fields and data types to those which actually exist.

Taking the conclusive verification of the correctness of an information system a step further, it would be efficient in the process of initial development and later adaptation if, whenever the database removes or alters a table or field that any references to that table or field referenced in SQL or a script in any client that would have resulted in the client trying to execute SQL on a non-existent object that the development framework automatically changes the SQL or script so that it is valid or disables the invalid SQL or script in the client. In addition, if, whenever the database changes or removes a data type, any assignment of a value returned by the database into a variable at the client that would have resulted in an incompatible and invalid assignment, the development framework automatically changes the data type of the variable to a compatible data type or disables the assignment in the client.

Turning the process the other way around, if a client attempts to change any SQL or script that would have resulted in the client trying to execute SQL or a rule referring a non-existent object in the database, the development framework automatically disallows the invalid SQL. Likewise, if a client attempts to change the data type of a variable being assigned a value from the database, the development framework automatically disallows the assignment.

Missing from the present art is a way of ensuring that whenever a client is changed, dependencies are verified to ensure they refer to existing tables and fields and that the data types are compatible and, whenever a database is changed, all the dependencies in every client are verified to ensure they refer to existing tables and fields and that the data types are compatible.

STATEMENT OF INNOVATION

The present invention, Run-the-Office, is a framework application that enables end-users to design any kind of information system which stores the kind of information the end-user's organization needs and enforces the kind of rules the end-user's organization demands in their processes so that the correctness of the system can be ensured without having to test every combination of behaviour at run-time. This is achieved by storing all the meta data describing the system in the database where triggers maintain the integrity of the meta data and loading the meta data into framework clients which generate the kind of information system defined.

INTRODUCTION TO DRAWINGS

FIG. 1 is a block diagram of the database, client and external function libraries embodying the present invention.

FIG. 2 is a more detailed diagram of the meta data and content data stored and the triggers that validate it in the database.

FIG. 3 is a more detailed diagram of the meta data and content data loaded and the interpreter that validates it in the client.

FIG. 4 is a diagram of the form definition interface with the widget types that can be added to the form and the property editor.

FIG. 5 is a diagram of the table definition interface.

FIG. 6 is a diagram of the dataset definition interface.

FIG. 7 is a diagram of the rule definition interface.

DETAILED DESCRIPTION

Run-the-Office solves the issue of ensuring that whenever a client 2 is changed, all dependencies are verified to ensure they refer to existing tables, fields and data types and that the data types are compatible. Run-the-Office also ensures that whenever a database 1 is changed, all dependencies in every client 2 are verified to ensure they refer to existing tables, fields and data types and that the data types are compatible.

It does this by making each client 2 a framework. The framework contains classes from which the client 2 dynamically creates objects like data types, datasets, forms, widgets and scripts. The definitions of which objects to create and their properties are provided by meta data 21 which is loaded 4 from the database 1 as soon as the client 2 connects to the database 1. The database 1 stores the meta data in tables and fields where, generally, each class is represented as a table, each customizable property of that class is represented as a field in that table and the instances of those classes are stored as rows in the table. The database 1 stores the meta data which defines data types, datasets, forms, widgets and scripts.

Each type of object created by the database 1 structure is also stored in the database 1 with each type of object generally represented as a table, the properties of those types of objects are represented as fields in that table and the instances of those types of objects are stored as rows in the table. The database 1 also stores the meta data which defines data types, tables, fields and rules.

By storing the definitions of the database 1 and clients 2 in the database 1 as meta data, triggers 25 provided by the database 1 are used to conclusively verifying the correctness the information system development framework by ensuring that all references used are always valid and all data types used are always compatible.

The clients 2 can be assured of correctness, irrespective of whether the database 1 was changed through the control of client 2 or outside the control of the client 2, because the database 1 will ensure the integrity of the meta data when it is inserted, updated or deleted. The client 2, being a framework, dynamically creates its data types, datasets, forms, widgets and scripts from the meta data loaded 4 from the database 1 on connecting to the database 1 and, because of this, can always be assured of correctness.

Run-the-Office uses the Firebird client-server, relational database which has support for transactions, triggers and the ability to call functions in dynamically loaded libraries 3. The clients 2 for Run-the-Office are developed in Qt/C++ which supports object-oriented programming and the dynamic creation and destruction of objects.

The design of the present invention distinguishes between two different types of meta data 21, system meta data 23 and application meta data 24. These are sometimes just called system data 23 and application data 24. The database 1 structures which store system data 23 are predefined by the framework and are common to all information systems based on the Run-the-Office framework. System data 23 includes data which describes the data types, tables, fields, datasets, forms, widgets and scripts. Application data 24 includes data which describes tables and fields specific to the domain and which are used to store content data 22.

The data types, also known as domains, required by the Run-the-Office framework are stored in the database 1 in a table called MetaDomain and loaded 4 by the clients 2 into instances of a class called MetaDomain.

Because the Run-the-Office framework uses the Firebird database 1 which stores domains in table RDB$FIELDS the framework can be certain that all domains listed MetaDomain exist in the database 1 by using trigger on table RDB$FIELDS so that as domains are added, updated and removed in Firebird the meta data listed in MetaDomain is synchronized.

The MetaDomain table has fields Identity of type integer, Caption of type varchar, Name of type varchar, Type of type enum {smallint, integer, double, date, time, timestamp, varchar, blob}, CharacterLength of type integer, CharacterSet of enum {utf-8, acsii} and SubType of enum {binary, text}. Identity is used as the primary key to uniquely identify a row. Caption is used in the client 2 as a user-friendly name for the data type. Name is Firebird's name for the domain. The Type enumeration lists those types supported by both Firebird and the clients 2. CharacterLength represents the length of varchar types. The CharacterSet enumeration lists those character sets supported by both Firebird and the clients 2. The SubType enumeration lists those blob subtypes supported by both Firebird and the clients 2.

The MetaDomain class has properties corresponding to the fields stored in the MetaDomain table. The MetaDomain class has properties Identity of type integer, Caption of type string, Name of type string, Type of type enum {boolean, integer, double, date, time, timestamp, varchar, blob}, CharacterLength of type integer, CharacterSet of enum {utf-8, acsii} and SubType of enum {binary, text}.

When the client 2 connects to the database 1 the rows from table MetaDomain are read 4 and instances of class MetaDomain are created for each row in table MetaDomain with the values of the properties of each instance of the MetaDomain class assigned to the values of the fields in the corresponding row of table MetaDomain.

The tables required by the Run-the-Office framework are stored in the database 1 in a table called MetaTable and loaded 4 by the clients 2 into instances of a class called MetaTable.

Because the Run-the-Office framework uses the Firebird database 1 which stores tables in table RDB$RELATIONS the framework can be certain that all tables listed MetaTable exist in the database 1 by using trigger on table RDB$RELATIONS so that as tables are added, updated and removed in Firebird the meta data listed in MetaTable is synchronized.

The MetaTable table has fields Identity of type integer, Caption of type varchar, Name of type varchar, PrimaryKey of type integer, OnValidateScript as integer and IsSystem of type smallint. Identity is used as the primary key to uniquely identify a row. Caption is used in the client 2 as a user-friendly name for the table. Name is Firebird's name for the table. PrimaryKey is a foreign key which references a row in the Identity field in table MetaField which represents the primary key field. OnValidateScript is a foreign key which references a row in the Identity field in table MetaScript which represents the validation script for the table. IsSystem is used by the client 2 to prevent the user from removing a table which is used in the 23.

The MetaTable class has properties corresponding to the fields stored in the MetaTable table. The MetaTable class has properties Identity of type integer, Caption of type string, Name as type string, ForeignKey of type integer, OnValidateScript as integer and IsSystem of type boolean.

When the client 2 connects to the database 1 the rows from table MetaTable are read 4 and instances of class MetaTable are created for each row in table MetaTable with the values of the properties of each instance of the MetaTable class assigned to the values of the fields in the corresponding row of table MetaTable.

The fields required by the Run-the-Office framework are stored in the database 1 in a table called MetaField and loaded 4 by the clients 2 into instances of a class called MetaField.

Because the Run-the-Office framework uses the Firebird database 1 which stores fields in table RDB$RELATION_FIELDS the framework can be certain that all fields listed MetaField exist in the database 1 by using trigger on table RDB$RELATION_FIELDS so that as fields are added, updated and removed in Firebird the meta data listed in MetaField is synchronized.

The MetaField table has fields Identity of type integer, Caption of type varchar, Name of type varchar, Domain of type integer, Table of type integer, OnValidateScript as integer and IsSystem of type smallint. Identity is used as the primary key to uniquely identify a row. Caption is used in the client 2 as a user-friendly name for the field. Name is Firebird's name for the field. Domain is a foreign key which references a row in the Identity field in table MetaDomain which represents the domain of the field. Table is a foreign key which references a row in the Identity field in table MetaTable which represents the table to which the field belongs. OnValidateScript is a foreign key which references a row in the Identity field in table MetaScript which represents the validation script for the field. IsSystem is used by the client 2 to prevent the user from removing a field which is used in the system data 23. 33.

The MetaField class has properties corresponding to the fields stored in the MetaField table. The MetaField class has properties Identity of type integer, Caption of type string, Name of type string, Domain of type integer, Table of type integer, OnValidateScript as integer and IsSystem of type boolean.

When the client 2 connects to the database 1 the rows from table MetaField are read 4 and instances of class MetaField are created for each row in table MetaField with the values of the properties of each instance of the MetaField class assigned to the values of the fields in the corresponding row of table MetaField.

The complexity of datasets demands that it be stored in more than one table. In the present invention, datasets are broken down into the entities and columns referenced, and the joins and filter applied.

The datasets required by the Run-the-Office framework are stored in the database 1 in a table called MetaDataSet and loaded 4 by the clients 2 into instances of a class called MetaDataSet. The MetaDataSet table has fields Identity of type integer and Filter of type integer. Identity is used as the primary key to uniquely identify a row. Filter is a foreign key which references a row in the Identity field in table MetaDataSetFilter which represents any filter on the dataset.

The MetaDataSet class has properties corresponding to the fields stored in the MetaDataSet table. The MetaDataSet class has properties Identity of type integer and Filter of type integer. The class also has an method, string* constructSQL( ) const, that constructs and returns a valid SQL statement from the definition of the MetaDataSet.

When the client 2 connects to the database 1 the rows from table MetaDataSet are read 4 and instances of class MetaDataSet are created for each row in table MetaDataSet with the values of the properties of each instance of the MetaDataSet class assigned to the values of the fields in the corresponding row of table MetaDataSet.

The tables referenced in each dataset by the Run-the-Office framework are stored in the database 1 in a table called MetaDataSetEntity and loaded 4 by the clients 2 into instances of a class called MetaDataSetEntity.

The MetaDataSetEntity table has fields Identity of type integer, DataSet of type integer and Table of type integer. Identity is used as the primary key to uniquely identify a row. DataSet is a foreign key which references a row in the Identity field in table MetaDataSet which represents the data set of which the entity is part. Table is a foreign key which references a row in the Identity field in table MetaTable which the entity references.

The MetaDataSetEntity class has properties corresponding to the fields stored in the MetaDataSetEntity table. The MetaDataSetEntity class has properties Identity of type integer, DataSet of type integer and Table of type integer.

When the client 2 connects to the database 1 the rows from table MetaDataSetEntity are read 4 and instances of class MetaDataSetEntity are created for each row in table MetaDataSetEntity with the values of the properties of each instance of the MetaDataSetEntity class assigned to the values of the fields in the corresponding row of table MetaDataSetEntity.

The fields referenced in each entity in the Run-the-Office framework are stored in the database 1 in a table called MetaDataSetColumn and loaded 4 by the clients 2 into instances of a class called MetaDataSetColumn.

The MetaDataSetColumn table has fields Identity of type integer, Entity of type integer and Field of type integer. Identity is used as the primary key to uniquely identify a row. Entity is a foreign key which references a row in the Identity field in table MetaDataSetEntity which represents the entity of which the column is part. Field is a foreign key which references a row in the Identity field in table MetaField which the column references.

The MetaDataSetColumn class has properties corresponding to the fields stored in the MetaDataSetColumn table. The MetaDataSetColumn class has properties Identity of type integer, Entity of type integer and Field of type integer.

When the client 2 connects to the database 1 the rows from table MetaDataSetColumn are read 4 and instances of class MetaDataSetColumn are created for each row in table MetaDataSetColumn with the values of the properties of each instance of the MetaDataSetColumn class assigned to the values of the fields in the corresponding row of table MetaDataSetColumn.

The joins referenced between each entity in the Run-the-Office framework are stored in the database 1 in a table called MetaDataSetJoin and loaded 4 by the clients 2 into instances of a class called MetaDataSetJoin.

The MetaDataSetJoin table has fields Identity of type integer, DataSet of type integer, LeftColumn of type integer, RightColumn of type integer and Type of enum {innerjoin, fullouterjoin, leftouterjoin, rightouterjoin}. Identity is used as the primary key to uniquely identify a row. DataSet is a foreign key which references a row in the Identity field in table MetaDataSet which represents the data set of which the entity is part. LeftColumn is a foreign key which references a row in the Identity field in table MetaDataSetColumn which represents the column that the left part of the join references. RightColumn is a foreign key which references a row in the Identity field in table MetaDataSetColumn which represents the column that the right part of the join references. Type represents the type of join from the list of joins available in both Firebird and the clients 2.

The MetaDataSetJoin class has properties corresponding to the fields stored in the MetaDataSetJoin table. The MetaDataSetJoin class has properties Identity of type integer, LeftColumn of type integer, RightColumn of type integer and Type of enum {fullouterjoin, leftouterjoin, rightouterjoin}.

When the client 2 connects to the database 1 the rows from table MetaDataSetJoin are read 4 and instances of class MetaDataSetJoin are created for each row in table MetaDataSetJoin with the values of the properties of each instance of the MetaDataSetJoin class assigned to the values of the fields in the corresponding row of table MetaDataSetJoin.

The filters referenced in the datasets in the Run-the-Office framework are stored in the database 1 in a table called MetaDataSetFilter and loaded 4 by the clients 2 into instances of a class called MetaDataSetFilter.

The MetaDataSetFilter table has fields Identity of type integer, DataSet of type integer and Quantifier of enum {alltrue, anytrue}. Identity is used as the primary key to uniquely identify a row. DataSet is a foreign key which references a row in the Identity field in table MetaDataSet which represents the data set to which the filter applies. Quantifier represents the quantifier of the filter tests which determines how many of the tests must pass for the condition to be successful.

The MetaDataSetFilter class has properties corresponding to the fields stored in the MetaDataSetFilter table. The MetaDataSetFilter class has properties Identity of type integer, DataSet of type integer and Quantifier of enum {alltrue, anytrue}.

When the client 2 connects to the database 1 the rows from table MetaDataSetFilter are read 4 and instances of class MetaDataSetFilter are created for each row in table MetaDataSetFilter with the values of the properties of each instance of the MetaDataSetFilter class assigned to the values of the fields in the corresponding row of table MetaDataSetFilter.

The tests referenced in the dataset filter in the Run-the-Office framework are stored in the database 1 in a table called MetaFilterTest and loaded 4 by the clients 2 into instances of a class called MetaFilterTest.

The MetaFilterTest table has fields Identity of type integer, Filter of type integer, Function of type integer and Index of type integer. Identity is used as the primary key to uniquely identify a row. Filter is a foreign key which references a row in the Identity field in table MetaDataSetFilter which represents the filter of which the test is part. Function is a foreign key which references a row in the Identity field in table MetaFilterFunction which represents the function which returns a boolean value that is executed to test the condition. Index represents the index position of the test in the condition.

The MetaFilterTest class has properties corresponding to the fields stored in the MetaFilterTest table. The MetaFilterTest class has properties Identity of type integer, Filter of type integer, Function of type integer and Index of type integer.

When the client 2 connects to the database 1 the rows from table MetaFilterTest are read 4 and instances of class MetaFilterTest are created for each row in table MetaFilterTest with the values of the properties of each instance of the MetaFilterTest class assigned to the values of the fields in the corresponding row of table MetaFilterTest.

The functions executed in the filter tests in the Run-the-Office framework are stored in the database 1 in a table called MetaFilterFunction and loaded 4 by the clients 2 into instances of a class called MetaFilterFunction.

The MetaFilterFunction table has fields Identity of type integer and Prototype of type integer. Identity is used as the primary key to uniquely identify a row. Prototype is a foreign key which references a row in the Identity field in table MetaFunctionPrototype which represents the function that is executed.

The MetaFilterFunction class has properties corresponding to the fields stored in the MetaFilterFunction table. The MetaFilterFunction class has properties Identity of type integer and Prototype of type integer.

When the client 2 connects to the database 1 the rows from table MetaFilterFunction are read 4 and instances of class MetaFilterFunction are created for each row in table MetaFilterFunction with the values of the properties of each instance of the MetaFilterFunction class assigned to the values of the fields in the corresponding row of table MetaFilterFunction.

The arguments passed into functions executed in the filter tests by the Run-the-Office framework are stored in the database 1 in a table called MetaFilterArgument and loaded 4 by the clients 2 into instances of a class called MetaFilterArgument.

The MetaFilterArgument table has fields Identity of type integer, Function of type integer, Parameter of type integer, FieldArgument of type integer, FunctionArgument of type integer, LiteralArgument of type binary blob and LiteralDomain of type integer. Identity is used as the primary key to uniquely identify a row. Function is a foreign key which references a row in the Identity field in table MetaFilterFunction which identifies the function in which the argument is included. Parameter is a foreign key which references a row in the Identity field in table MetaFunctionParameter which represents the parameter corresponding to the argument. FieldArgument is a foreign key which references a row in the Identity field in table MetaField which identifies the field name whose value is passed as the argument. FunctionArgument is a foreign key which references a row in the Identity field in table MetaFilterFunction which identifies the function name whose return value is passed as the argument. LiteralArgument is a blob which can carry any value. LiteralDomain is a foreign key which references a row in the Identity field in table MetaDomain which identifies the domain of the literal argument.

The MetaFilterArgument class has properties corresponding to the fields stored in the MetaFilterArgument table. The MetaFilterArgument class has properties Identity of type integer, Function of type integer, Parameter of type integer, FieldArgument of type integer, FunctionArgument of type integer, LiteralArgument of type byte array and LiteralDomain of type integer.

When the client 2 connects to the database 1 the rows from table MetaFilterArgument are read 4 and instances of class MetaFilterArgument are created for each row in table MetaFilterArgument with the values of the properties of each instance of the MetaFilterArgument class assigned to the values of the fields in the corresponding row of table MetaFilterArgument.

The forms required by the Run-the-Office framework are stored in the database 1 in a table called MetaForm and loaded 4 by the clients 2 into instances of a class called MetaForm.

The MetaForm table has fields Identity of type integer, Caption of type varchar and DataSet of type integer. Identity is used as the primary key to uniquely identify a row. Caption is used in the client 2 as the user-friendly caption for the form. DataSet is a foreign key which references a row in the Identity field in table MetaDataSet which represents the dataset that provides the data that the form reads, updates, inserts and deletes.

The MetaForm class has properties corresponding to the fields stored in the MetaForm table. The MetaForm class has properties Identity of type integer, Caption of type string and DataSet of type integer. The class also has a virtual method, form* createForm( ) const, that creates and returns a form instance which can be shown in the client 2.

When the client 2 connects to the database 1 the rows from table MetaForm are read 4 and instances of class MetaForm are created for each row in table MetaForm with the values of the properties of each instance of the MetaForm class assigned to the values of the fields in the corresponding row of table MetaForm.

Forms are containers for widgets. Widgets is a general term for buttons, controls or editors. Widgets can come in a variety of types. These include line edits, combo boxes, check boxes, radio buttons and push buttons.

The widgets required by the Run-the-Office framework are stored in the database 1 in a table called MetaWidget and loaded 4 by the clients 2 into instances of a class called MetaWidget.

The MetaWidget table has fields Identity of type integer, Name of type varchar, Form of type integer, Top of type integer, Left of type integer, Height of type integer and Width of type integer. Identity is used as the primary key to uniquely identify a row. Name is used to identify the name of the widget class since there are different types of widgets used in the client 2. Form is a foreign key which references a row in the Identity field in table MetaForm which represents the form in which the widget is contained. Top represents the top or y coordinate of the widget on the form. Left represents the left or x coordinate of the widget on the form. Height represents the height of the widget on the form. Width represents the width of the widget on the form.

The MetaWidget class has properties corresponding to the fields stored in the MetaWidget table. The MetaWidget class has properties Identity of type integer, Name of type string, Form of type integer, Top of type integer, Left of type integer, Height of type integer and Width of type integer. The class also has an abstract virtual method, widget* createWidget( ) const=0, which in subclasses creates and returns a valid widget instance which can be displayed on a form.

Because each class of widget has a different set of properties which can be customized by the end-user, each widget type is stored in a separate table with each widget table having a one-to-one relationship with the MetaWidget table. Likewise, each class of widget in the client 2 is defined as a subclass of the MetaWidget class with properties added to the subclass to support the particular attributes of that widget and a non-abstract virtual method, widget* createWidget( ) const, that creates and returns a valid widget instance which can be displayed a form. The database 1 structures and client 2 classes for two widgets, line edit and push button, are described.

The properties and events available on each line edit created by the Run-the-Office framework are stored in the database 1 in a table called MetaLineEdit and loaded 4 by the clients 2 into instances of a class called MetaLineEdit.

The MetaLineEdit table has fields Identity of type integer, Widget of type integer and Column of type integer. Identity is used as the primary key to uniquely identify a row. Widget is a foreign key which references a row in the Identity field in table MetaWidget with which MetaLineEdit has a one-to-one relationship. Column is a foreign key which references a row in the Identity field in table MetaDataSetColumn which identifies the column in the form's dataset that provides the data that the line edit reads, updates, inserts and deletes.

The MetaLineEdit class has properties corresponding to the fields stored in the MetaLineEdit table. The MetaLineEdit class has properties Identity of type integer and Column of type integer. The MetaLineEdit class does not need to store the value stored in field Widget because the MetaLineEdit class is a subclass of MetaWidget and is aware of property values of its ancestor class. The class also has a virtual method, widget* createWidget( ) const, that creates and returns a valid line edit instance, which can be displayed on a form. The actual instance of the line edit widget is not created at the time that the MetaLineEdit instance is created.

When the client 2 connects to the database 1 the unique Names from table MetaWidget are read 4. Using the Name field in table MetaWidget, the client 2 constructs an SQL statement using that Name, “MetaLineEdit”, and a join is made between tables MetaWidget and MetaLineEdit where MetaWidget.Identity=MetaLineEdit.Widget and the rows in the dataset are read 4 and instances of class MetaLineEdit are created for each row in the dataset with the values of the properties of each instance of the MetaLineEdit class assigned to the values of the fields in the corresponding row of the dataset, except Widget, with the values of the fields read 4 from MetaWidget assigned to the ancestor class MetaWidget and the values of the fields from MetaLineEdit assigned to instances of the subclass MetaLineEdit.

The properties and events available on each push button created by the Run-the-Office framework are stored in the database 1 in a table called MetaPushButton and loaded 4 by the clients 2 into instances of a class called MetaPushButton.

The MetaPushButton table has fields Identity of type integer, Caption of type varchar, Widget of type integer and OnClickScript of type integer. Identity is used as the primary key to uniquely identify a row. Caption stores the caption which appears on the push button. Widget is a foreign key which references a row in the Identity field in table MetaWidget with which MetaPushButton has a one-to-one relationship. OnClickScript is a foreign key which references a row in the Identity field in table MetaScript which represents the script that will be executed when the push button is clicked.

The MetaPushButton class has properties corresponding to the fields stored in the MetaPushButton table. The MetaPushButton class has properties Identity of type integer, Caption of type string and OnClickScript of type integer. The MetaPushButton class does not need to store the value stored in Widget because the MetaPushButton class is a subclass of MetaWidget and is aware of property values on its ancestor class. The class also has a virtual method, widget* createWidget( ) const, that creates and returns a valid push button instance which can be displayed on a form. The actual instance of the push button widget is not created at the time that the MetaPushButton instance is created.

When the client 2 connects to the database 1 the unique Names from table MetaWidget are read 4. Using the Name field in table MetaWidget the client 2 constructs an SQL statement using that Name, “MetaPushButton”, and a join is made between tables MetaWidget and MetaPushButton where MetaWidget.Identity=MetaPushButton.Widget and the rows in the dataset are read 4 and instances of class MetaPushButton are created for each row in the dataset with the values of the properties of each instance of the MetaPushButton class assigned to the values of the fields in the corresponding row of the dataset with the values of the fields read 4 from MetaWidget assigned to the ancestor class MetaWidget and the values of the fields from MetaPushButton assigned to the subclass MetaPushButton.

The scripts and filters are implemented by calling compiled functions. The present invention provides a range of maths, string, date, time and timestamp functions among others in the form of libraries 3 which can be dynamically loaded from the database 1 and any clients 2 and the appropriate function called.

The list of available externally callable functions available to the Run-the-Office framework are stored in the database 1 in a table called MetaFunctionPrototype and loaded 4 by the clients 2 into instances of a class called MetaFunctionPrototype.

Because the Run-the-Office framework uses the Firebird database 1 which stores externally callable functions in table RDB$FUNCTIONS, the framework can be certain that all functions listed in MetaFunctionPrototype are registered in the database 1 by using a trigger on table RDB$FUNCTIONS so that as functions are registered, changed and unregistered in Firebird the meta data listed in MetaFunctionPrototype is synchronized.

The MetaFunctionPrototype table has fields Identity of type integer, Caption of type varchar, Name of type varchar, Library of type varchar, EntryPoint of type varchar and ReturnParameter of type integer. Identity is used as the primary key to uniquely identify a row. Caption is used in the client 2 as a user-friendly name for the function. Name is used to uniquely identify the name of the function. Library is used to identify the name of the library to load. EntryPoint is used to identify the function in the library to call. ReturnParam is a foreign key which references a row in the Identity field in table MetaDomain which represents the data type of the return value.

The MetaFunctionPrototype class has properties corresponding to the fields stored in the MetaFunctionPrototype table. The MetaFunctionPrototype class has properties Identity of type integer, Caption of type string, Name of type string, Library of type string, EntryPoint of type string and ReturnParameter of type integer.

When the client 2 connects to the database 1 the rows from table MetaFunctionPrototype are read 4 and instances of class MetaFunctionPrototype are created for each row in table MetaFunctionPrototype with the values of the properties of each instance of the MetaFunctionPrototype class assigned to the values of the fields in the corresponding row of table MetaFunctionPrototype.

The parameters for each externally callable function listed in MetaFunctionPrototype are stored by the Run-the-Office framework in the database 1 in a table called MetaFunctionParameter and loaded 4 by the clients 2 into instances of a class called MetaFunctionParameter.

Because the Run-the-Office framework uses the Firebird database 1 which stores the parameters for externally callable functions in table RDB$FUNCTION_ARGUMENTS the framework can be certain that all function parameters listed MetaFunctionParameter are registered in the database 1 by using trigger on table RDB$FUNCTION_ARGUMENTS so that as parameters are registered, updated and unregistered in Firebird the meta data listed in MetaFunctionParameter is synchronized.

The MetaFunctionParameter table has fields Identity of type integer, Caption of type varchar, Function of type integer, Domain of type integer and Index of type integer. Identity is used as the primary key to uniquely identify a row. Caption is used in the client 2 as a user-friendly name for the parameter. Function is a foreign key which references a row in the Identity field in table MetaFunctionPrototype of which the parameter is a part. Domain is a foreign key which references a row in the Identity field in table MetaDomain which indicates the domain of the parameter. Index is the index of the parameter in the function.

The MetaFunctionParameter class has properties corresponding to the fields stored in the MetaFunctionParameter table. The MetaFunctionParameter class has properties Identity of type integer, Caption of type string, Function of type integer, Domain of type integer and Index of type integer.

When the client 2 connects to the database 1 the rows from table MetaFunctionParameter are read 4 and instances of class MetaFunctionParameter are created for each row in table MetaFunctionParameter with the values of the properties of each instance of the MetaFunctionParameter class assigned to the values of the fields in the corresponding row of table MetaFunctionParameter.

Scripts are the expression of what are variously called constraints, actions or rules. The complexity of a script demands that it be stored in more than one table. In the present invention, a script is broken down into blocks, conditions, tests, expressions, functions and arguments.

The scripts required by the Run-the-Office framework are stored in the database 1 in a table called MetaScript and loaded 4 by the clients 2 into instances of a class called MetaScript. The MetaScript table has one field Identity of type integer which is used as the primary key to uniquely identify a row.

When the client 2 connects to the database 1 the rows from table MetaScript are read 4 and instances of class MetaScript are created for each row in table MetaScript with the values of the properties of each instance of the MetaScript class assigned to the values of the fields in the corresponding row of table MetaScript.

The blocks referenced in the scripts by the Run-the-Office framework are stored in the database 1 in a table called MetaScriptBlock and loaded 4 by the clients 2 into instances of a class called MetaScriptBlock.

The MetaScriptBlock table has fields Identity of type integer, Script of type integer, Condition of type integer and Index of type integer. Identity is used as the primary key to uniquely identify a row. Script is a foreign key which references a row in the Identity field in table MetaScript which represents the script of which the block is part. Condition is a foreign key which references a row in the Identity field in table MetaScriptCondition which represents the first condition of the block. Index represents the index position of the block in the script.

The MetaScriptBlock class has properties corresponding to the fields stored in the MetaScriptBlock table. The MetaScriptBlock class has properties Identity of type integer, Script of type integer, Condition of type integer and Index of type integer.

When the client 2 connects to the database 1 the rows from table MetaScriptBlock are read 4 and instances of class MetaScriptBlock are created for each row in table MetaScriptBlock with the values of the properties of each instance of the MetaScriptBlock class assigned to the values of the fields in the corresponding row of table MetaScriptBlock.

The conditions referenced in the script blocks by the Run-the-Office framework are stored in the database 1 in a table called MetaScriptCondition and loaded 4 by the clients 2 into instances of a class called MetaScriptCondition.

The MetaScriptCondition table has fields Identity of type integer, ElseCondition of type integer and Quantifier of enum {alltrue, anytrue}. Identity is used as the primary key to uniquely identify a row. ElseCondition is a self-referencing foreign key which references a row in the Identity field in the same MetaScriptCondition table and represents the next condition which is tested when the present condition fails. Quantifier represents the quantifier of the condition which determines how many of the tests must pass for the present condition to be successful.

The MetaScriptCondition class has properties corresponding to the fields stored in the MetaScriptCondition table. The MetaScriptCondition class has properties Identity of type integer, ElseCondition of type integer and Quantifier of enum {alltrue, anytrue}.

When the client 2 connects to the database 1 the rows from table MetaScriptCondition are read 4 and instances of class MetaScriptCondition are created for each row in table MetaScriptCondition with the values of the properties of each instance of the MetaScriptCondition class assigned to the values of the fields in the corresponding row of table MetaScriptCondition.

The tests referenced in the script conditions by the Run-the-Office framework are stored in the database 1 in a table called MetaScriptTest and loaded 4 by the clients 2 into instances of a class called MetaScriptTest.

The MetaScriptTest table has fields Identity of type integer, Condition of type integer, Function of type integer and Index of type integer. Identity is used as the primary key to uniquely identify a row. Condition is a foreign key which references a row in the Identity field in table MetaScriptCondition which represents the condition of which the test is part. Function is a foreign key which references a row in the Identity field in table MetaScriptFunction and represents the function which returns a boolean value that is executed to test the condition. Index represents the index position of the test in the condition.

The MetaScriptTest class has properties corresponding to the fields stored in the MetaScriptTest table. The MetaScriptTest class has properties Identity of type integer, Condition of type integer, Function of type integer and Index of type integer.

When the client 2 connects to the database 1 the rows from table MetaScriptTest are read 4 and instances of class MetaScriptTest are created for each row in table MetaScriptTest with the values of the properties of each instance of the MetaScriptTest class assigned to the values of the fields in the corresponding row of table MetaScriptTest.

The expressions referenced in the scripts in the Run-the-Office framework are stored in the database 1 in a table called MetaScriptExpression and loaded 4 by the clients 2 into instances of a class called MetaScriptExpression.

The MetaScriptExpression table has fields Identity of type integer, Condition of type integer, Function of type integer and Index of type integer. Identity is used as the primary key to uniquely identify a row. Condition is a foreign key which references a row in the Identity field in table MetaCondition which represents the condition of which the expression is part and is executed when the condition succeeds. Function is a foreign key which references a row in the Identity field in table MetaScriptFunction which represents the function which is executed when a condition succeeds. Index represents the index position of the expression.

The MetaScriptExpression class has properties corresponding to the fields stored in the MetaScriptExpression table. The MetaScriptExpression class has properties Identity of type integer, Condition of type integer, Function of type integer and Index of type integer.

When the client 2 connects to the database 1 the rows from table MetaScriptExpression are read 4 and instances of class MetaScriptExpression are created for each row in table MetaScriptExpression with the values of the properties of each instance of the MetaScriptExpression class assigned to the values of the fields in the corresponding row of table MetaScriptExpression.

The functions executed in the script tests and expressions by the Run-the-Office framework are stored in the database 1 in a table called MetaScriptFunction and loaded 4 by the clients 2 into instances of a class called MetaScriptFunction.

The MetaScriptFunction table has fields Identity of type integer and Prototype of type integer. Identity is used as the primary key to uniquely identify a row. Prototype is a foreign key which references a row in the Identity field in table MetaFunctionPrototype which represents the function that is executed.

The MetaScriptFunction class has properties corresponding to the fields stored in the MetaScriptFunction table. The MetaScriptFunction class has properties Identity of type integer and Prototype of type integer.

When the client 2 connects to the database 1 the rows from table MetaScriptFunction are read 4 and instances of class MetaScriptFunction are created for each row in table MetaScriptFunction with the values of the properties of each instance of the MetaScriptFunction class assigned to the values of the fields in the corresponding row of table MetaScriptFunction.

The arguments passed into functions executed in the script tests and expressions by the Run-the-Office framework are stored in the database 1 in a table called MetaScriptArgument and loaded 4 by the clients 2 into instances of a class called MetaScriptArgument.

The MetaScriptArgument table has fields Identity of type integer, Function of type integer, Parameter of type integer, FieldArgument of type integer, FunctionArgument of type integer, LiteralArgument of type binary blob and LiteralDomain of type integer. Identity is used as the primary key to uniquely identify a row. Function is a foreign key which references a row in the Identity field in table MetaScriptFunction which identifies the function in which the argument is being included. Parameter is a foreign key which references a row in the Identity field in table MetaFunctionParameter which represents the parameter corresponding to the argument. FieldArgument is a foreign key which references a row in the Identity field in table MetaField which identifies the field name whose value is passed as the argument. FunctionArgument is a foreign key which references a row in the Identity field in table MetaScriptFunction which identifies the function name whose return value is passed as the argument. LiteralArgument is a blob which can carry any value. LiteralDomain is a foreign key which references a row in the Identity field in table MetaDomain which identifies the domain of the literal argument.

The MetaScriptArgument class has properties corresponding to the fields stored in the MetaScriptArgument table. The MetaScriptArgument class has properties Identity of type integer, Function of type integer, Parameter of type integer, FieldArgument of type integer, FunctionArgument of type integer, LiteralArgument of type byte array and LiteralDomain of type integer.

When the client 2 connects to the database 1 the rows from table MetaScriptArgument are read 4 and instances of class MetaScriptArgument are created for each row in table MetaScriptArgument with the values of the properties of each instance of the MetaScriptArgument class assigned to the values of the fields in the corresponding row of table MetaScriptArgument.

The reader will have noted the use of foreign keys to reference primary keys or the Identity field in the Run-the-Office system tables described above. Not only do these relationships need to be enforced but further constraints need to be applied. Triggers 25 are created on the tables such that whenever a row is inserted, updated or deleted, PSQL (Procedural SQL), which embodies the rule, runs in a trigger 25 to enforce the constraint and maintain the integrity of the meta data stored in the database 1. These are now described.

An AFTER INSERT trigger 25 is applied to the Firebird table RDB$FIELDS so that as domains are inserted in Firebird the meta data listed in MetaDomain is similarly inserted. A BEFORE INSERT trigger 25 on table MetaDomain commits the transaction when the values in the row correspond to values in table RDB$FIELDS. An AFTER UPDATE trigger 25 is applied to the Firebird table RDB$FIELDS so that as domains are altered in Firebird the meta data listed in MetaDomain is similarly updated. A BEFORE UPDATE trigger 25 on table MetaDomain commits the transaction when the values in the row correspond to values in table RDB$FIELDS. An AFTER DELETE trigger 25 is applied to the Firebird table RDB$FIELDS so that as domains are deleted in Firebird the meta data listed in MetaDomain is similarly deleted. Firebird will not allow a domain to be removed which is being used by an object in the database 1. A BEFORE DELETE trigger 25 is applied to table MetaDomain which ensures that if the values in the row correspond to values in the table RDB$FIELDS that the deletion request is ignored and the row cannot be removed.

An AFTER INSERT trigger 25 is applied to the Firebird table RDB$RELATIONS so that as tables are inserted in Firebird the meta data listed in MetaTable is similarly inserted. A BEFORE INSERT trigger 25 on table MetaTable commits the transaction when the values in the row correspond to values in table RDB$RELATIONS. An AFTER UPDATE trigger 25 is applied to the Firebird table RDB$RELATIONS so that as tables are altered in Firebird the meta data listed in MetaTable is similarly updated. A BEFORE UPDATE trigger 25 on table MetaTable commits the transaction when the values in the row correspond to values in table RDB$RELATIONS. An AFTER DELETE trigger 25 is applied to the Firebird table RDB$RELATIONS so that as tables are deleted in Firebird the meta data listed in MetaTable is similarly deleted. A BEFORE DELETE trigger 25 is applied to table MetaTable which ensures that if the values in the row correspond to values in the table RDB$RELATIONS that the deletion request is ignored and the row cannot be removed. An AFTER DELETE trigger is applied to table MetaTable which ensures that any references to the table in MetaDataSetEntity.Table are removed. References to the table in MetaField.Table do not have be removed because the AFTER DELETE trigger on RDB$RELATION_FIELDS achieves this.

An AFTER INSERT trigger 25 is applied to the Firebird table RDB$RELATION_FIELDS so that as fields are inserted in Firebird the meta data listed in MetaField is similarly inserted. A BEFORE INSERT trigger 25 on table MetaField commits the transaction when the values in the row correspond to values in table RDB$RELATION_FIELDS. An AFTER UPDATE trigger 25 is applied to the Firebird table RDB$RELATION_FIELDS so that as fields are altered in Firebird the meta data listed in MetaField is similarly updated. A BEFORE UPDATE trigger 25 on table MetaField commits the transaction when the values in the row correspond to values in table RDB$RELATION_FIELDS. An AFTER DELETE trigger is applied to the Firebird table RDB$RELATION_FIELDS so that as fields are deleted in Firebird the meta data listed in MetaField is similarly deleted. A BEFORE DELETE trigger 25 is applied to table MetaField which ensures that if the values in the row correspond to values in the table RDB$RELATION_FIELDS that the deletion request is ignored and the row cannot be removed. An AFTER DELETE trigger is applied to table MetaField which ensures that any references to the field in MetaDataSetColumn.Field, MetaFilterArgument.FieldArgument and MetaScriptArgument.FieldArgument are removed. References to the field in MetaTable.PrimaryKey do not have be removed because the AFTER DELETE trigger on RDB$RELATIONS achieves this.

The Run-the-Office framework ships with a range of string, maths, date, time and timestamp functions among others which are distributed in dynamically loading function libraries 3. Each function in each library 3 needs to be registered in the database 1 using the DECLARE EXTERNAL FUNCTION statement. One example is the “multiply” function which takes two parameters of type integer and returns an integer.

An AFTER INSERT trigger 25 is applied to the Firebird table RDB$FUNCTIONS so that as externally callable functions are inserted in Firebird the meta data listed in MetaFunctionPrototype is similarly inserted. A BEFORE INSERT trigger 25 on table MetaFunctionPrototype commits the transaction when the values in the row correspond to values in table RDB$FUNCTIONS. An AFTER UPDATE trigger 25 is applied to the Firebird table RDB$FUNCTIONS so that as externally callable functions are altered in Firebird the meta data listed in MetaFunctionPrototype is similarly updated. A BEFORE UPDATE trigger 25 on table MetaFunctionPrototype commits the transaction when the values in the row correspond to values in table RDB$FUNCTIONS. An AFTER DELETE trigger is applied to the Firebird table RDB$FUNCTIONS so that as externally callable functions are deleted in Firebird the meta data listed in MetaFunctionPrototype is similarly deleted. A BEFORE DELETE trigger 25 is applied to table MetaFunctionPrototype which ensures that if the values in the row correspond to values in the table RDB$FUNCTIONS that the deletion request is ignored and the row cannot be removed. An AFTER DELETE trigger is applied to table MetaFunctionPrototype which ensures that any references to the function prototype in MetaFilterFunction.Prototype and MetaScriptFunction.Prototype are removed. References to the function prototype in MetaFunctionParameter.Function do not have be removed because the AFTER DELETE trigger on RDB$FUNCTION_ARGUMENTS achieves this.

An AFTER INSERT trigger 25 is applied to the Firebird table RDB$FUNCTION_ARGUMENTS so that as arguments for externally callable functions are inserted in Firebird the meta data listed in MetaFunctionParameter is similarly inserted. A BEFORE INSERT trigger 25 on table MetaFunctionParameter commits the transaction when the values in the row correspond to values in table RDB$FUNCTION_ARGUMENTS. An AFTER UPDATE trigger 25 is applied to the Firebird table RDB$FUNCTION_ARGUMENTS so that as arguments for externally callable functions are altered in Firebird the meta data listed in MetaFunctionParameter is similarly updated. A BEFORE UPDATE trigger 25 on table MetaFunctionParameter commits the transaction when the values in the row correspond to values in table RDB$FUNCTION_ARGUMENTS. An AFTER DELETE trigger is applied to the Firebird table RDB$FUNCTION_ARGUMENTS so that as arguments for externally callable functions are deleted in Firebird the meta data listed in MetaFunctionParameter is similarly deleted. A BEFORE DELETE trigger 25 is applied to table MetaFunctionParameter which ensures that if the values in the row correspond to values in the table RDB$FUNCTION_ARGUMENTS that the deletion request is ignored and the row cannot be removed. An AFTER DELETE trigger is applied to table MetaFunctionParameter which ensures that any references to the function parameter in MetaFilterArgument.Parameter and MetaScriptArgument.Parameter are removed.

This covers the important synchronization checks between Firebird's domains, tables, fields, functions and parameters and the domains, tables, fields, functions and parameters listed in MetaDomain, MetaTable, MetaField, MetaFunctionPrototype and MetaFunctionParameter. Further referential integrity constraints need to be applied to all the meta tables such that where a foreign key exists there is a trigger 25 which enforces the rule that the foreign key refers to a primary key.

Further constraints on the types of data need to be enforced. For example, the Column property of MetaLineEdit refers to a field which must exist in the form's dataset on which the line edit exists. A field referenced as an argument in a function used in a filter must exist in the dataset to which the filter belongs. Other constraints ensure that values in fields are constrained by the enumerations available to that field. Such constraints can be enforced with Firebird's trigger 25 PSQL and the reader familiar with the art does not need further details to understand what kinds of constraints to apply or how to enforce these since further explanation does not enhance the understanding of this invention.

In the Run-the-Office clients 2, a class called MetaSystem 7, also referred to as the meta system 7, loads 4 the meta data from the database 1 when the client 2 connects to the database 1. The MetaSystem 7 class has properties MetaDomains of type metalist, MetaTables of type metalist, MetaFields of type metalist, MetaDataSets of type metalist, MetaDataSetEntities of type metalist, MetaDataSetColumns of type metalist, MetaDataSetJoins of type metalist, MetaDataSetFilters of type metalist, MetaFilterTests of type metalist, MetaFilterFunctions of type metalist, MetaFilterArguments of type metalist, MetaForms of type metalist, MetaWidgets of type metalist, MetaFunctionPrototypes of type metalist, MetaFunctionParameters of type metalist, MetaScripts of type metalist, MetaScriptBlocks of type metalist, MetaScriptConditions of type metalist, MetaScriptTests of type metalist, MetaScriptExpressions of type metalist, MetaScriptFunctions of type metalist and MetaScriptArguments of type metalist. The metalist data type is a list with a flag on each item of enum {retain, update, add, remove}. The metalists are stored as private variables internal to the meta system 7 and instances of the classes listed above are returned as constants so that they cannot be altered or deleted outside the control of the meta system 7. The meta system 7 provides all the constraints on the client 2 which are provided by triggers 25 on the database 1.

As the MetaDomains are read 4 from the database 1 instances of class MetaDomain are created for each row in table MetaDomain with the values of the properties of each instance of the MetaDomain class assigned to the values of the fields in the corresponding row of table MetaDomain and the instance of the class is added to the metalist MetaDomains with the value of the flag set to {retain}.

As the MetaTables are read 4 from the database 1 instances of class MetaTable are created for each row in table MetaTable with the values of the properties of each instance of the MetaTable class assigned to the values of the fields in the corresponding row of table MetaTable and the instance of the class is added to the metalist MetaTables with the value of the flag set to {retain}.

As the MetaFields are read 4 from the database 1 instances of class MetaField are created for each row in table MetaField with the values of the properties of each instance of the MetaField class assigned to the values of the fields in the corresponding row of table MetaField and the instance of the class is added to the metalist MetaFields with the value of the flag set to {retain}.

As the MetaDataSets are read 4 from the database 1 instances of class MetaDataSet are created for each row in table MetaDataSet with the values of the properties of each instance of the MetaDataSet class assigned to the values of the fields in the corresponding row of table MetaDataSet and the instance of the class is added to the metalist MetaDataSets with the value of the flag set to {retain}.

As the MetaDataSetEntities are read 4 from the database 1 instances of class MetaDataSetEntity are created for each row in table MetaDataSetEntity with the values of the properties of each instance of the MetaDataSetEntity class assigned to the values of the fields in the corresponding row of table MetaDataSetEntity and the instance of the class is added to the metalist MetaDataSetEntities with the value of the flag set to {retain}.

As the MetaDataSetColumns are read 4 from the database 1 instances of class MetaDataSetColumn are created for each row in table MetaDataSetColumn with the values of the properties of each instance of the MetaDataSetColumn class assigned to the values of the fields in the corresponding row of table MetaDataSetColumn and the instance of the class is added to the metalist MetaDataSetColumns with the value of the flag set to {retain}.

As the MetaDataSetJoins are read 4 from the database 1 instances of class MetaDataSetJoin are created for each row in table MetaDataSetJoin with the values of the properties of each instance of the MetaDataSetJoin class assigned to the values of the fields in the corresponding row of table MetaDataSetJoin and the instance of the class is added to the metalist MetaDataSetJoins with the value of the flag set to {retain}.

As the MetaDataSetFilters are read 4 from the database 1 instances of class MetaDataSetFilter are created for each row in table MetaDataSetFilter with the values of the properties of each instance of the MetaDataSetFilter class assigned to the values of the fields in the corresponding row of table MetaDataSetFilter and the instance of the class is added to the metalist MetaDataSetFilter with the value of the flag set to {retain}.

As the MetaFilterTests are read 4 from the database 1 instances of class MetaFilterTest are created for each row in table MetaFilterTest with the values of the properties of each instance of the MetaFilterTest class assigned to the values of the fields in the corresponding row of table MetaFilterTest and the instance of the class is added to the metalist MetaFilterTest with the value of the flag set to {retain}.

As the MetaFilterFunctions are read 4 from the database 1 instances of class MetaFilterFunction are created for each row in table MetaFilterFunction with the values of the properties of each instance of the MetaFilterFunction class assigned to the values of the fields in the corresponding row of table MetaFilterFunction and the instance of the class is added to the metalist MetaFilterFunction with the value of the flag set to {retain}.

As the MetaFilterArguments are read 4 from the database 1 instances of class MetaFilterArgument are created for each row in table MetaFilterArgument with the values of the properties of each instance of the MetaFilterArgument class assigned to the values of the fields in the corresponding row of table MetaFilterArgument and the instance of the class is added to the metalist MetaFilterArgument with the value of the flag set to {retain}.

As the MetaForms are read 4 from the database 1 instances of class MetaForm are created for each row in table MetaForm with the values of the properties of each instance of the MetaForm class assigned to the values of the fields in the corresponding row of table MetaForm and the instance of the class is added to the metalist MetaForms with the value of the flag set to {retain}.

The unique rows for values in the Name field from the MetaWidget table are read 4 from the database 1. For each row read 4, an SQL statement using the Name value is constructed that reads 4 all the rows from the dataset which joins MetaWidget and the table corresponding to the Name value. Instances of the MetaWidget subclass with the name corresponding to the Name value are created for each row in dataset with the values of the properties of each instance of the MetaWidget subclass assigned to the values of the fields in the corresponding row of the dataset and the instance of the subclass is added to the metalist MetaWidgets with the value of the flag set to {retain}.

As the MetaFunctionPrototypes are read 4 from the database 1 instances of class MetaFunctionPrototype are created for each row in table MetaFunctionPrototype with the values of the properties of each instance of the MetaFunctionPrototype class assigned to the values of the fields in the corresponding row of table MetaFunctionPrototype and the instance of the class is added to the metalist MetaFunctionPrototypes with the value of the flag set to {retain}.

As the MetaFunctionParameters are read 4 from the database 1 instances of class MetaFunctionParameter are created for each row in table MetaFunctionParameter with the values of the properties of each instance of the MetaFunctionParameter class assigned to the values of the fields in the corresponding row of table MetaFunctionParameter and the instance of the class is added to the metalist MetaFunctionParameters with the value of the flag set to {retain}.

As the MetaScripts are read 4 from the database 1 instances of class MetaScript are created for each row in table MetaScript with the values of the properties of each instance of the MetaScript class assigned to the values of the fields in the corresponding row of table MetaScript and the instance of the class is added to the metalist MetaScripts with the value of the flag set to {retain}.

As the MetaScriptBlocks are read 4 from the database 1 instances of class MetaScriptBlock are created for each row in table MetaScriptBlock with the values of the properties of each instance of the MetaScriptBlock class assigned to the values of the fields in the corresponding row of table MetaScriptBlock and the instance of the class is added to the metalist MetaScriptBlocks with the value of the flag set to {retain}.

As the MetaScriptConditions are read 4 from the database 1 instances of class MetaScriptCondition are created for each row in table MetaScriptCondition with the values of the properties of each instance of the MetaScriptCondition class assigned to the values of the fields in the corresponding row of table MetaScriptCondition and the instance of the class is added to the metalist MetaScriptConditions with the value of the flag set to {retain}.

As the MetaScriptTests are read 4 from the database 1 instances of class MetaScriptTest are created for each row in table MetaScriptTest with the values of the properties of each instance of the MetaScriptTest class assigned to the values of the fields in the corresponding row of table MetaScriptTest and the instance of the class is added to the metalist MetaScriptTests with the value of the flag set to {retain}.

As the MetaScriptExpressions are read 4 from the database 1 instances of class MetaScriptExpression are created for each row in table MetaScriptExpression with the values of the properties of each instance of the MetaScriptExpression class assigned to the values of the fields in the corresponding row of table MetaScriptExpression and the instance of the class is added to the metalist MetaScriptExpressions with the value of the flag set to {retain}.

As the MetaScriptFunctions are read 4 from the database 1 instances of class MetaScriptFunction are created for each row in table MetaScriptFunction with the values of the properties of each instance of the MetaScriptFunction class assigned to the values of the fields in the corresponding row of table MetaScriptFunction and the instance of the class is added to the metalist MetaScriptFunctions with the value of the flag set to {retain}.

As the MetaScriptArguments are read 4 from the database 1 instances of class MetaScriptArgument are created for each row in table MetaScriptArgument with the values of the properties of each instance of the MetaScriptArgument class assigned to the values of the fields in the corresponding row of table MetaScriptArgument and the instance of the class is added to the metalist MetaScriptArguments with the value of the flag set to {retain}.

Once the MetaSystem 7 has loaded 4 all the meta data from the database 1, it is able to display the list of application-specific forms for the user to open. In an information system framework like Run-the-Office the end-user must define the data structures, forms and rules their organization requires. User-defined tables, fields are identified by a value of false in the field IsSystem in tables MetaTable and MetaField. User-defined data is also referred to as application data 24, 34.

Using the Run-the-Office framework, to create a new form, the user clicks a button which sends a signal to the MetaSystem 7 to create a new instance of class MetaForm which it adds to the MetaForms metalist and sets the flag to {add}. The meta system 7 calls an integer generator on the database 1 to supply a unique value which the meta system 7 assigns to the Identity property. The MetaSystem 7 then calls the method createForm( ) on the instance of class MetaForm in order to create the new form with the values of its properties set to a default value. The new form can then be displayed to the user in the application. Using the form interface, the user needs to define a dataset with which the form widgets can interact. This means having application-specific tables and fields before the dataset can be defined.

Within the form interface the user can access the table definition interface where the user defines a table, setting the property Caption to a unique value assigned by the user, checked by scanning the list of MetaTables, which, for illustrative purposes is “Products”. This sends a signal to the MetaSystem 7 to create a new instance of class MetaTable which it adds to the MetaTables metalist and sets the flag to {add}. The meta system 7 calls an integer generator on the database 1 to supply a unique value which the meta system 7 assigns to the Identity property. The value of the IsSystem property is set to false. For each new instance of MetaTable created, the meta system 7 creates a new instance of MetaField which it adds to the MetaFields metalist and sets the flag to {add} setting the property Identity to the value returned by calling an integer generator on the database 1 to supply a unique value. It searches through the list of MetaDomains until it finds the MetaDomain where the Type property is equal to “integer” and assigns the value of the MetaDomain's Identity to the property Domain in MetaField. The value of the Caption property is set to a “Identity” and the value of the IsSystem property is set to true. The value of the PrimaryKey property in MetaTable is set to the value of Identity in the new MetaField instance. The value of Name in MetaTable is set to the value returned by calling a varchar generator on the database 1 to supply a unique name.

Within the table definition interface 51, the user then defines fields 53 to add to that table. For each field 53 added, the user sets the property Caption 56, which, for illustrative purposes are “Name”, “Image” and “Value”, and selects a domain 57 from the list of domains listed in MetaDomains and a signal is sent to the MetaSystem 7 to create a new instance of class MetaField which it adds to the MetaFields metalist setting the flag to {add}. The meta system 7 scans the list of MetaFields which belong to the table to ensure that the value of the Caption 56 is unique. If not, the meta system 7 will not create a new instance of class MetaField until the user enters a unique value. The meta system 7 calls an integer generator on the database 1 to supply a unique value which the meta system 7 assigns to the Identity property. The value of the IsSystem property is set to false. The Identity property of the MetaTable instance identifying the table to which the field belongs is assigned to the MetaField's Table property in the certainty that the table exists in the meta system 7. The Identity property of the MetaDomain instance identifying the domain of the field is assigned to the MetaField's Domain property in the certainty that the domain exists in the meta system 7. The value of Name in MetaField is set to the value returned by calling a varchar generator on the database 1 to supply a unique name.

The user can now define the dataset with which the form widgets can interact. Within the form definition interface 41 the user can access the dataset definition interface 61 where the user defines the entities 63 selecting from the list of application-specific tables 62 available in the meta system 7's MetaTables metalist where the value of the IsSystem flag is false. The entities 63 can be added to the dataset definition interface 61 by dragging the table 62 from the list of application-specific tables onto the dataset definition interface 61. On adding the first entity 63, the meta system 7 creates an instance of MetaDataSet and adds the instance to the metalist of DataSets and sets the flag to {add}. The meta system 7 calls an integer generator on the database 1 to supply a unique value which the meta system 7 assigns to the Identity property. The value of the Identity property is then assigned to the value of the DataSet property of the MetaForm instance.

For each entity 63 added, the meta system 7 creates an instance of MetaDataSetEntity and adds the instance to the metalist of DataSetEntities setting the flag to {add}. The meta system 7 calls an integer generator on the database 1 to supply a unique value which the meta system 7 assigns to the Identity property. The Identity property of the MetaDataSet instance identifying the dataset to which the entity belongs is assigned to the MetaDataSetEntity's DataSet property in the certainty that the dataset exists in the meta system 7. The Identity property of the MetaTable instance identifying the table which the entity references is assigned to the MetaDataSetEntity's Table property in the certainty that the table exists in the meta system 7.

The caption of each field in the entity's table 63 is displayed in the dataset definition interface 61 next to a check box. With each field 64 displayed, the value of the Identity property from the field's MetaField instance is stored so that as the user selects a field 64, by checking the check box, to be included in the dataset SQL statement, the meta system 7 creates an instance of MetaDataSetColumn and adds the instance to the metalist of DataSetColumns setting the flag to {add}. The meta system 7 calls an integer generator on the database 1 to supply a unique value which the meta system 7 assigns to the Identity property. The Identity property of the MetaDataSetEntity instance identifying the entity 63 to which the column 64 belongs is assigned to the MetaDataSetColumn's Entity property in the certainty that the entity exists in the meta system 7. The Identity property of the MetaField instance identifying the field which the column references is assigned to the MetaDataSetColumn's Field property in the certainty that the field exists in the meta system 7. By unchecking the check box 64 the meta system 7 removes the MetaDataSetColumn instance from the metalist of DataSetColumns and destroys the instance.

Within the dataset definition interface 61, the user then drags a field from one entity 63 and drops it onto another entity 63 to define a join 65 between the entities. The interface will create a join 65 when the data types of the fields 64 dragged and dropped between entities 63 are compatible. Data types are compatible when the Domain property in the MetaField identified by the Field property in the MetaDataSetColumn instances are the same. When the dataset definition interface 61 permits a join 65, a signal is sent to the MetaSystem 7 to create a new instance of class MetaDataSetJoin which it adds to the MetaDataSetJoins metalist setting the flag to {add}. The meta system 7 calls an integer generator on the database 1 to supply a unique value which the meta system 7 assigns to the Identity property. The Identity property of the MetaDataSet instance identifying the dataset to which the join belongs is assigned to the MetaDataSetJoin's DataSet property in the certainty that the dataset exists in the meta system 7. The value of the LeftColumn property is set to the Identity value of the MetaDataSetColumn that was dragged. The value of the RightColumn property is set to the Identity value of the MetaDataSetColumn onto which the field was dropped. By default the value of the Type enum is set to {innerjoin}. Within the dataset definition interface 61, a join 65 is displayed as a line between the field 64 identified as the left column and the field 64 identified as the right column. Clicking on the line 65 the user can change the type of join 65 to a value of “innerjoin”, “fullouterjoin”, “leftouterjoin” or “rightouterjoin”. On changing the join 65 value between “innerjoin”, “fullouterjoin”, “leftouterjoin” or “rightouterjoin” the value of the Type property in the MetaDataSetJoin instance is updated.

Within the dataset definition interface 61, the user defines a filter 66 which is a condition, a quantifier 67 and some tests. The meta data is provided by instances of the classes MetaDataSetFilter and MetaFilterTest. To define a filter 66, the user then selects the quantifier 67 from a combo box of {alltrue, anytrue} and adds tests to the filter. As the user adds the first test, the meta system 7 creates an instance of MetaDataSetFilter and adds it to the metalist of MetaDataSetFilters setting the flag to {add}. The meta system 7 calls an integer generator on the database 1 to supply a unique value which the meta system 7 assigns to the Identity property. The Identity property of the MetaDataSet instance identifying the dataset to which the filter belongs is assigned to the MetaDataSetFilter's DataSet property. On changing the quantifier value between “alltrue” and “anytrue” the value of the Quantifier property in the MetaDataSetFilter instance is updated.

The interface for defining filters 66 operates is a manner similar to the rules which is described later. By clicking on the “<Filter>” section, the user is able to choose from a list of functions which return a domain compatible with the type boolean and which take at least one parameter. For illustrative purposes, the user decides to apply a filter on the dataset where the “Name” field starts with “T”. By selecting “<Text> starts with <Text>”, which is derived from the caption for the MetaFunctionPrototype, “%1 starts with %2” for the “starts_with” function in the string library 3 and the captions of the MetaFunctionParameter's corresponding to the MetaFunctionPrototype, the interface provides a “<Text>” section either side of the “starts with” text representing the arguments of type string to be included in the call to the “starts_with” function call. The number, position and type of arguments needed by the functions in the tests are provided by the meta system 7 by accessing the metalist of MetaFunctionParameters searching for instances of MetaFunctionParameter which reference the MetaFunctionPrototype. Each MetaFunctionParameter referencing the MetaFunctionPrototype is ordered using the index. By clicking on either “<Text>” section, the user is able to select from a list of functions which return a value compatible with string, a list of available fields in the form's dataset of a domain compatible with string or type in a literal value which can be converted to a string. The user selects the fields, “Name” and types in the literal value “T” 68, 69 such that the filter becomes “WHERE starts_with (Name', ‘T’)”.

For each test added, a signal is sent to the MetaSystem 7 to create a new instance of class MetaFilterTest which it adds to the MetaFilterTests metalist setting the flag to {add}. The meta system 7 calls an integer generator on the database 1 to supply a unique value which the meta system 7 assigns to the Identity property. The Identity property of the MetaDataSetFilter instance identifying the filter to which the test belongs is assigned to the MetaFilterTest's Filter property. The position of the test in the dataset definition interface 61 is assigned to the Index property.

Because the test has one function 69, the meta system 7 creates an instance of MetaFilterFunction and adds the instance to the metalist of MetaFilterFunctions setting the flag to {add}. The meta system 7 calls an integer generator on the database 1 to supply a unique value which the meta system 7 assigns to the Identity property. The meta system 7 is aware of the MetaFunctionPrototype selected by the user and the value of the Identity property is assigned to the value of the Prototype property of the MetaFilterFunction. The Identity of the MetaFilterFunction, representing the function to be executed, is assigned to the value of the Function property of the MetaFilterTest.

For each argument 68, 69 defined in the filter definition interface, the meta system 7 creates an instance of MetaFilterArgument setting the flag to {add}. The meta system 7 calls an integer generator on the database 1 to supply a unique value which the meta system 7 assigns to the Identity property.

The Identity of the MetaFilterFunction of which the argument is a part is assigned to the value of the Function property of the MetaFilterArgument. The meta system 7 is aware of the MetaFunctionParameter completed by the user and the value of the Identity property is assigned to the value of the Parameter property of the MetaFilterArgument. The meta system 7 is also aware of the MetaField set as the argument for the first parameter and the value of the Identity property of the MetaField is assigned to the value of the FieldArgument property of the MetaFilterArgument. The meta system 7 is likewise aware of the literal string value typed in by the user which is assigned to the value of the LiteralArgument property of the MetaFilterArgument and the LiteralDomain property of the MetaFilterArgument is assigned the Identity value of the “integer” MetaDomain.

With the dataset in place, the user is able to drag widgets 42 onto the form. The list of available widget types 42 is provided by the Run-the-Office framework. Once dropped onto the form, the meta system 7 creates an instance of the appropriate MetaWidget subclass which is added to the metalist of MetaWidgets setting the flag to {add}. The meta system 7 calls an integer generator on the database 1 to supply a unique value which the meta system 7 assigns to the Identity property. The Identity property of the MetaForm instance identifying the form on which the widget appears is assigned to the MetaWidget's Form property. The meta system 7 calls the virtual widget* createWidget( ) const method which creates an instance of the widget which is displayed on the form. The position and size of the widget is stored in the MetaWidget's Top, Left, Height and Width 47 properties. As the user repositions and resizes the widget on the form, the MetaWidget properties Top, Left, Height and Width 47 are updated.

The properties specific to any widget 44 on the form are displayed in a property editor 45. In the case of an instance of MetaLineEdit the user can edit the Column value 46. The value of the Column identifies the column in the form's dataset that the widget edits. On selecting a column, the value of the field's Caption property is displayed as the widget's caption 43 and the value of the field's OnValidateScript 48 property can be edited by the user. The OnValidateScript 48 property identifies the script to be executed when the value displayed in the widget is updated or when the field is updated. When the user edits the values of the properties 45, the corresponding properties in the MetaWidget subclass and the field 46 to which the widget is connected are updated. Because the property editor 45 is aware of the fields in the form's dataset, it lists only those columns 46 in the form's dataset from which the user can select. This ensures the validity of the information system.

Once the user is satisfied with the design, a save button in the form definition interface 41 provides the ability to save 5 the changes made to the meta system 7 back to the database 1 in the certainty that the data listed in the meta system 7 corresponds exactly to the data stored in the database 1.

For meta instances of MetaDomain where the value of the Flag property is {add}, the meta system 7 constructs and executes a CREATE DOMAIN statement using the Name, Type, CharacterLength, CharacterSet and SubType properties followed by an UPDATE SQL statement to set the values of the properties in table MetaDomain. For meta instances of MetaTable where the value of the Flag property is {add}, the meta system 7 constructs and executes a CREATE TABLE statement using the MetaTable Name property with the list of MetaField instances which belong to that table using the MetaField Name and Domain properties followed by a CREATE TRIGGER for the event types BEFORE INSERT, AFTER INSERT, BEFORE UPDATE, AFTER UPDATE, BEFORE DELETE and AFTER DELETE to create a trigger 26 using the MetaTable Name property with a trigger name derived from the trigger event type and the table name and then followed by an UPDATE SQL statement to set the values of the properties in tables MetaTable and MetaField. For meta instances of MetaField where the value of the Flag property is {add} and the corresponding MetaTable flag is {retain}, the meta system 7 constructs and executes an ALTER TABLE statement using the MetaField Name and Domain properties followed by an UPDATE SQL statement to set the values of the properties in tables MetaField. The meta system 7 constructs and executes INSERT SQL statements on all other meta instances where the flag is {add}. As the database 1 processes the SQL statements, triggers 25 in the tables being inserted and updated revalidate the input to ensure that the data complies with the constraints applied.

For meta instances of MetaDomain where the value of the Flag property is {update}, the meta system 7 constructs and executes an ALTER DOMAIN statement using the Name, Type, CharacterLength, CharacterSet and SubType properties followed by an UPDATE SQL statement to set the values of the properties in table MetaDomain. For meta instances of MetaTable where the value of the Flag property is {update}, the meta system 7 constructs and executes an ALTER TABLE statement using the MetaTable Name property with the list of MetaField instances which belong to that table followed by an UPDATE SQL statement to set the values of the properties in tables MetaTable and MetaField. For meta instances of MetaField where the value of the Flag property is {add} and the corresponding MetaTable flag is {retain}, the meta system 7 constructs and executes an ALTER TABLE statement using the MetaField Name and Domain properties followed by an UPDATE SQL statement to set the values of the properties in tables MetaField. The meta system 7 constructs and executes UPDATE SQL statements on all other meta instances where the flag in {update}. As the database 1 processes the SQL statements, triggers 25 in the tables being updated revalidate the input to ensure that the data complies with the constraints applied.

For meta instances of MetaDomain where the value of the Flag property is {remove}, the meta system 7 constructs and executes a DROP DOMAIN statement with the Name property. For meta instances of MetaTable where the value of the Flag property is {remove}, the meta system 7 constructs and executes a DROP TABLE statement with the Name property. For meta instances of MetaField where the value of the Flag property is {remove} and the corresponding MetaTable flag is {retain}, the meta system 7 executes an ALTER TABLE statement using the MetaTable Name property and the list of MetaField instances which are still retained in the table. The meta system 7 constructs and executes DELETE SQL statements on all other meta instances where the flag is {remove}. As the database 1 processes the SQL statements, triggers 25 in the tables being deleted revalidate the input to ensure that the data complies with the constraints applied.

One case in which the correctness of the client 2 may be in conflict with the database 1 is where the client 2 has connected to the database 1, loaded 4 its meta data from the database 1, created the objects specified by the meta data and then the database 1 structure is changed outside the control of the client 2. This situation is resolved in the present invention because the database 1 used, Firebird, will reject a request to modify its structure while an object is in use by a client 2. A further case in which the correctness of the client 2 may be in conflict with the database 1 is where the client 2 has connected to the database 1, loaded 4 its meta data from the database 1, created the objects specified by the meta data and then a row in a table defining the meta data is changed outside the control of the client 2. This situation is resolved in the present invention because the framework has applied a constraint on the database 1 to reject a request to modify its meta data while more than one client 2 is connected to the database 1.

Within the form definition interface 41, the user clicks a button so that the form's data can be edited. On clicking the button the MetaDataSet returns the SQL from the MetaDataSet method string constructSQL( ) const which the form opens. Because Firebird can call functions in dynamically loadable functions, functions defined in the SQL filter clause can be accessed. Once open, the form informs each widget which retrieves any field value from the dataset and displays it allowing the user to read, insert, update and delete data.

At a later stage, the user may decide to adapt the information system by deleting the field “Value” and adding fields “Cost”, “Markup” and “Price” with a formula script on the value of “Price”. The user opens the client 2 and connects to the database 1 so that the meta system 7 loads 4 the meta data from the database 1. Using the Run-the-Office table definition interface 51 within the form interface framework, the user selects the table 52 whose caption is “Products” and chooses an option to delete the field “Value”.

The table definition interface 51 stores the MetaField for the field displayed in the interface. When the user selects to delete a field 53 from the table definition interface 51, a signal is sent to the meta system 7 which sets the flag on the applicable MetaField instance to {remove}. Because the meta system 7 understands the dependencies between the meta objects, the meta system 7 updates the flags on all dependent objects to {remove}. In this instance, having set the flag to the applicable MetaField instance to {remove} the meta system 7 iterates over the metalist MetaDataSetColumns to find all values in the property Field in each MetaDataSetColumn which are equal to the Identity value in the MetaField and sets the MetaDataSetColumn flag to {remove}. Setting the MetaDataSetColumn flag to {remove} then causes a domino effect such that all meta objects referencing the MetaDataSetColumn have their flags set to {delete} and all objects referencing those objects have their flags set to {delete}. For example, the meta system 7 iterates over the metalist MetaWidgets to find all values in the property Field in each MetaWidget subclass which are equal to the Identity value in the MetaField and sets the MetaWidget flag to {remove}. Setting the MetaWidget flag to {remove} then causes a domino effect such that all meta objects referencing the MetaWidget have their flags set to {delete} and all objects referencing those objects have their flags set to {delete}. Further, the meta system 7 also iterates over the metalist MetaScriptArguments to find all values in the property FieldArgument in each MetaScriptArgument which are equal to the Identity value in the MetaField and sets the MetaScriptArgument flag to {remove}. Setting the MetaScriptArgument flag to {remove} then causes the MetaScriptFunction of which the MetaScriptArgument is a part to have its flag set to {delete} and this causes a domino effect such that all meta objects referencing the MetaScriptFunction have their flags set to {delete} and all objects referencing those objects have their flags set to {delete}.

The result of this domino effect is that in the Run-the-Office framework references to non-existent objects cannot occur and this helps to conclusively verify the correctness of the information system without needing to test every combination of behaviour at run-time. To fully verify the correctness of an information system, the framework needs to ensure that the types of objects referred to have an appropriate value. This is discussed below when scripting is discussed.

To be more user-friendly, the Run-the-Office client 2 framework first displays to the user all the references to the objects being deleted so that the user can visualize the effect of the change on the system. Once the user agrees by clicking a button, the cascading removal effect is performed. However, once the user saves 5 the changes back to the database 1, as described above, or edits the database 1 directly, no such confirmation is asked of the user and the triggers 25, 26 in the database 1 delete and update data automatically thus maintaining the integrity of the system.

The user can now add the fields, “Cost”, “Markup” and “Price” to the table “Products” as described above and drop instances of the MetaLineEdit widget onto the form. The user can now define a formula rule on field “Price” which is defined as “Cost” multiplied by “Markup”. From the property editor of the “Price” widget, the user can display the rule definition interface by clicking the OnValidateScript 48 property.

The rule definition interface is a point and select interface. A problem inherent in many rule definition interfaces is that the syntax of the language in which the rules are defined, for example Basic or JavaScript, require the user to be familiar with those languages and this entails ensuring that the syntax is correct so that the interpreter 7 can understand and execute the script. In addition, these other rule definition interfaces also allow the user to reference objects which might not exist in the system or to assign values to objects, methods, properties or functions which are of an incompatible type or to pass arguments into functions which are of an incompatible type. By providing a point and select rule definition interface, the Run-the-Office framework prevents the user from making errors and ensures the correctness of the information system without needing to test every combination of behaviour at run-time.

71 illustrates what the rule definition interface will display initially. By clicking on the “<Value>” section, the user is able to choose from a list of functions which return a domain compatible with the domain of the field “Price” or a list of available fields in the form's dataset of a domain compatible with the domain of the field “Price” 72. By selecting “<Number>×<Number>” 72, which is derived from the caption for the MetaFunctionPrototype, “%1×%2” for the “multiply” function in the maths library 3 and the captions of the MetaFunctionParameter's corresponding to the MetaFunctionPrototype, the rule definition interface provides a “<Number>” section either side of the “x” 73 representing the arguments of type integer to be included in the call to the “multiply” function call. The number, position and type of arguments needed by the function are provided by the meta system 7 by accessing the metalist of MetaFunctionParameters searching for instances of MetaFunctionParameter which reference the MetaFunctionPrototype. Each MetaFunctionParameter referencing the MetaFunctionPrototype is ordered using the index. By clicking on either “<Number>” 73 section, the user is able to select from a list of functions which return a value compatible with integer or a list of available fields in the form's dataset of a domain compatible with integer. For illustrative purposes the user selects the fields, “Cost” and “Markup” such that the formula rule on field “Price” is defined as “Cost” multiplied by “Markup” 75.

Once constructed, the meta system 7 creates an instance of MetaScript and adds the instance to the metalist of MetaScripts setting the flag to {add}. The meta system 7 calls an integer generator on the database 1 to supply a unique value which the meta system 7 assigns to the Identity property. For each block in the rule, the meta system 7 creates an instance of MetaScriptBlock and adds the instance to the metalist of MetaScriptBlocks setting the flag to {add}. The meta system 7 calls an integer generator on the database 1 to supply a unique value which the meta system 7 assigns to the Identity property. The Identity of the MetaScript of which the block is a part is assigned to the value of the Script property of the MetaScriptBlock.

The formula has one function which must exist within an expression and an expression is executed as a result of condition whose tests have passed successfully. While there are no tests, the meta system 7 creates an instance of MetaScriptCondition and adds the instance to the metalist of MetaScriptConditions setting the flag to {add}. The meta system 7 calls an integer generator on the database 1 to supply a unique value which the meta system 7 assigns to the Identity property. Because there is no else condition, the value of the property ElseCondition is left at 0 and the value of the property Quantifier is set to {alltrue}. The Identity of the MetaScriptCondition representing the first condition in the block is assigned to the value of the Condition property of the MetaScriptBlock.

The meta system 7 creates an instance of MetaScriptExpression and adds the instance to the metalist of MetaScriptExpressions setting the flag to {add}. The meta system 7 calls an integer generator on the database 1 to supply a unique value which the meta system 7 assigns to the Identity property. The Identity of the MetaScriptCondition which represents the condition of which the expression is part and is executed when the condition succeeds, is assigned to the value of the Condition property. Index represents the index position of the expression in the condition.

Because the formula has one function, the meta system 7 creates an instance of MetaScriptFunction and adds the instance to the metalist of MetaScriptFunctions setting the flag to {add}. The meta system 7 calls an integer generator on the database 1 to supply a unique value which the meta system 7 assigns to the Identity property. From the rule definition interface, the meta system 7 is aware of the MetaFunctionPrototype selected by the user and the value of the Identity property is assigned to the value of the Prototype property of the MetaScriptFunction. The Identity of the MetaScriptFunction, representing the function to be executed, is assigned to the value of the Function property of the MetaScriptExpression.

For each argument defined in the rule definition interface, the meta system 7 creates an instance of MetaScriptArgument setting the flag to {add}. The meta system 7 calls an integer generator on the database 1 to supply a unique value which the meta system 7 assigns to the Identity property. The Identity of the MetaScriptFunction of which the argument is a part is assigned to the value of the Function property of the MetaScriptArgument. From the rule definition interface, the meta system 7 is aware of the MetaFunctionParameter completed by the user and the value of the Identity property is assigned to the value of the Parameter property of the MetaScriptArgument. From the rule definition interface, the meta system 7 is aware of the MetaField set as the argument for the chosen parameter and the value of the Identity property of the MetaField is assigned to the value of the FieldArgument property of the MetaScriptArgument.

Once the user is satisfied with the design of the rule, a save button in the form definition interface 41 provides the ability to save 5 the changes made to the meta system 7 back to the database 1 in the certainty that the data listed in the meta system 7 corresponds exactly to the data stored in the database 1.

Within the form definition interface 41, the user clicks a button so that the form's data can be edited. On updating either the “Cost” or “Markup” values the value of the “Price” formula is recalculated. This is because the “Price” formula is dependent on the fields “Cost” and “Markup” so the Run-the-Office framework listens for updates on these fields and forces the field to recalculate.

The calculation is performed by running the script as defined in the OnValidateScript 48 property of “Price”. The script is executed by the interpreter 7 in the client 2. The interpreter 7 consists of a C++ while statement to iterate over the blocks of the script. Within the block iterator, the interpreter 7 has a C++ while statement to iterate over conditions with C++ break statements when a condition fulfils the tests and the expressions have been executed. Within the condition iterator, the interpreter 7 has a C++ while statement to iterate over the tests. Because each test is a function, the interpreter 7 loads the libraries 3 referenced in the test, calls the appropriate function and assigns the boolean return value from the function call to the condition which, using the condition's quantifier property, either moves to the next condition if the condition fails or iterates over the expressions if the condition succeeds. Because each expression is a function, the interpreter 7 loads the libraries 3 referenced in the expression, calls the appropriate function and assigns any return values from the function calls to any fields or functions referenced.

Just as there are different types of data, system data 23, 33, application data 24, 34 and content data 22, 32, there are different types of rules. For system 23, 33 and application data 24, 34, the rules are predefined by the Run-the-Office framework and implemented on the database 1 by triggers 25 and on the clients 2 by the meta system 7. For content data 22, 32 which are defined by the end-user and implemented on the database 1 by triggers 26 running the scripts which execute the externally callable functions 3 and on the clients 2 by running scripts through the interpreter 7 which execute the externally callable functions 3.

Like the predefined rules implemented on system 23, 33 and application data 24, 34 which are prevalidated by the meta system 7 and then again by the database 1 triggers 25 to ensure that the integrity of the system is maintained even when the system 23 and application 24 data is modified outside the control of one of the Run-the-Office clients 2, the user-defined rules implemented on content data 22, 32 are prevalidated on the client 2 by executing the scripts through the interpreter 7 and then validated again by the database 1 triggers 26 to ensure that the integrity of the system is maintained even when the content data 22 is modified outside the control of one of the Run-the-Office clients 2.

The user-defined validation scripts on the database 1 are executed by BEFORE INSERT and BEFORE UPDATE triggers 26 for the user-defined fields where the rule is defined in the OnValidateScript 48 property of the MetaField and by AFTER INSERT, AFTER UPDATE and AFTER DELETE triggers 26 for the user-defined tables where the rule is defined in the OnValidateScript 55 property of the MetaTable.

The trigger 26 validates user-defined fields by iterating over the fields in the user-defined table which it accesses from table MetaField using the identity of the script to run from the OnValidateScript 48 property. The trigger 26 consists of a Firebird PSQL WHILE . . . DO statement to iterate over the blocks of the script. Within the block iterator, the trigger 26 has a PSQL WHILE . . . DO statement to iterate over conditions with PSQL LEAVE statements when a condition fulfils the tests and the expressions have been executed. Within the condition iterator, the trigger 26 has a PSQL WHILE . . . DO statement to iterate over the tests. Because each test is a function, the functions are wrapped in Firebird's EXECUTE BLOCK statement which dynamically loads the libraries 3 referenced in the test, calls the appropriate function and assigns the boolean return value from the function call to the condition which, using the condition's quantifier property, either moves to the next condition if the condition fails or iterates over the expressions. Because each expression is a function, the function are wrapped in Firebird's EXECUTE BLOCK statement which dynamically loads the libraries 3 referenced in the expression, calls the appropriate function and assigns any return values from the function calls to any fields referenced.

The reader will notice that the user-defined scripts executed on the client 2 and the database 1 are identical and that, preferably, the scripts access the same externally callable function libraries 3 so that the rules are applied consistently. 

1. A system comprising a database which stores the system meta data, application meta data and rule meta data of the information system, which represent the structure of the information system, in tables and fields with triggers on the tables to ensure that the integrity of the system is maintained, and one or more clients which load the system meta data, application meta data and rule meta data from the database into a meta system object with rules on the meta system to ensure that the integrity of the system is maintained during each step of development without having to test every combination of behaviour at run-time.
 2. A system as claimed in claim 1 where system meta data, application meta data and rule meta data is loaded from the database into one or more client frameworks to define and from which to generate the information system clients.
 3. A system as claimed in claim 1 where rules on the database and the clients ensure the validity of system meta data, application meta data and rule meta data thus maintaining the integrity of the system.
 4. A system as claimed in claim 1 where validations of the system meta data, application meta data and rule meta data can be performed at the client, in a middleware application through which data is passed between the client and the database, on the database or any combination of these before the data is committed to the database.
 5. A system as claimed in claim 1 where rule meta data, which is executed by the database and clients call the same dynamically loaded function libraries.
 6. A system as claimed in claim 1 where clients permit only references to existing objects and options which are computationally compatible, as defined in the meta data, thus maintaining the integrity of the system during each stage of development.
 7. An information system substantially as herein described above and illustrated in the accompanying drawings. 